<template><div><p>本文档最新版为 <a href="https://learnku.com/docs/laravel/10.x" target="_blank" rel="noopener noreferrer">10.x</a>，旧版本可能放弃维护，推荐阅读最新版！</p>
<h2 id="laravel-passport" tabindex="-1"><a class="header-anchor" href="#laravel-passport"><span>Laravel Passport</span></a></h2>
<ul>
<li><a href="#introduction">介绍</a>
<ul>
<li><a href="#passport-or-sanctum">Passport 还是 Sanctum？</a></li>
</ul>
</li>
<li><a href="#installation">安装</a>
<ul>
<li><a href="#deploying-passport">部署 Passport</a></li>
<li><a href="#upgrading-passport">升级 Passport</a></li>
</ul>
</li>
<li><a href="#configuration">配置</a>
<ul>
<li><a href="#client-secret-hashing">客户端密钥哈希</a></li>
<li><a href="#token-lifetimes">令牌生命周期</a></li>
<li><a href="#overriding-default-models">覆盖默认模型</a></li>
<li><a href="#overriding-routes">覆盖路由</a></li>
</ul>
</li>
<li><a href="#issuing-access-tokens">发放访问令牌</a>
<ul>
<li><a href="#managing-clients">管理客户端</a></li>
<li><a href="#requesting-tokens">请求令牌</a></li>
<li><a href="#refreshing-tokens">刷新令牌</a></li>
<li><a href="#revoking-tokens">撤销令牌</a></li>
<li><a href="#purging-tokens">清除令牌</a></li>
</ul>
</li>
<li><a href="#code-grant-pkce">授权码授权与PKCE</a>
<ul>
<li><a href="#creating-a-auth-pkce-grant-client">创建客户端</a></li>
<li><a href="#requesting-auth-pkce-grant-tokens">请求令牌</a></li>
</ul>
</li>
<li><a href="#password-grant-tokens">密码授权令牌</a>
<ul>
<li><a href="#creating-a-password-grant-client">创建密码授权客户端</a></li>
<li><a href="#requesting-password-grant-tokens">请求令牌</a></li>
<li><a href="#requesting-all-scopes">请求所有范围</a></li>
<li><a href="#customizing-the-user-provider">自定义用户提供程序</a></li>
<li><a href="#customizing-the-username-field">自定义用户名字段</a></li>
<li><a href="#customizing-the-password-validation">自定义密码验证</a></li>
</ul>
</li>
<li><a href="#implicit-grant-tokens">隐式授权令牌</a></li>
<li><a href="#client-credentials-grant-tokens">客户端凭据授权令牌</a></li>
<li><a href="#personal-access-tokens">个人访问令牌</a>
<ul>
<li><a href="#creating-a-personal-access-client">创建个人访问客户端</a></li>
<li><a href="#managing-personal-access-tokens">管理个人访问令牌</a></li>
</ul>
</li>
<li><a href="#protecting-routes">保护路由</a>
<ul>
<li><a href="#via-middleware">通过中间件</a></li>
<li><a href="#passing-the-access-token">传递访问令牌</a></li>
</ul>
</li>
<li><a href="#token-scopes">令牌范围</a>
<ul>
<li><a href="#defining-scopes">定义范围</a></li>
<li><a href="#default-scope">默认范围</a></li>
<li><a href="#assigning-scopes-to-tokens">为令牌分配范围</a></li>
<li><a href="#checking-scopes">检查范围</a></li>
</ul>
</li>
<li><a href="#consuming-your-api-with-javascript">使用 JavaScript 消费你的 API</a></li>
<li><a href="#events">事件</a></li>
<li><a href="#testing">测试</a></li>
</ul>
<h2 id="介绍" tabindex="-1"><a class="header-anchor" href="#介绍"><span>介绍</span></a></h2>
<p><a href="https://github.com/laravel/passport" target="_blank" rel="noopener noreferrer">Laravel Passport</a> 在几分钟内为你的 Laravel 应用程序提供了完整的 OAuth2 服务器实现。Passport 构建在由 Andy Millington 和 Simon Hamp 维护的 <a href="https://github.com/thephpleague/oauth2-server" target="_blank" rel="noopener noreferrer">League OAuth2 server</a> 之上。</p>
<blockquote>
<p><strong>警告</strong><br>
本文档假定你已经熟悉 OAuth2。如果你对 OAuth2 一无所知，请在继续之前熟悉一下 OAuth2 的一般 <a href="https://oauth2.thephpleague.com/terminology/" target="_blank" rel="noopener noreferrer">术语</a> 和特性。</p>
</blockquote>
<h3 id="passport-还是-sanctum" tabindex="-1"><a class="header-anchor" href="#passport-还是-sanctum"><span>Passport 还是 Sanctum？</span></a></h3>
<p>在开始之前，你可能希望确定你的应用程序更适合使用 Laravel Passport 还是 <a href="https://learnku.com/docs/laravel/11.x/sanctum" target="_blank" rel="noopener noreferrer">Laravel Sanctum</a>。如果你的应用程序绝对需要支持 OAuth2，则应该使用 Laravel Passport。</p>
<p>然而，如果你尝试对单页面应用、移动应用程序进行身份验证，或者发放 API 令牌，你应该使用 <a href="https://learnku.com/docs/laravel/11.x/sanctum" target="_blank" rel="noopener noreferrer">Laravel Sanctum</a>。Laravel Sanctum 不支持 OAuth2；但它提供了一个更简单的 API 身份验证开发体验。</p>
<h2 id="安装" tabindex="-1"><a class="header-anchor" href="#安装"><span>安装</span></a></h2>
<p>你可以通过 <code v-pre>install:api</code> Artisan 命令安装 Laravel Passport：</p>
<div class="language-bash line-numbers-mode" data-highlighter="prismjs" data-ext="sh" data-title="sh"><pre v-pre class="language-bash"><code><span class="line">php artisan install:api <span class="token parameter variable">--passport</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>这个命令将发布并运行数据库迁移，用于创建你的应用程序需要存储 OAuth2 客户端和访问令牌的表。该命令还将创建生成安全访问令牌所需的加密密钥。</p>
<p>此外，该命令将询问你是否想要将 UUID 作为 Passport <code v-pre>Client</code> 模型的主键值，而不是自增整数。</p>
<p>运行 <code v-pre>install:api</code> 命令后，将 <code v-pre>Laravel\Passport\HasApiTokens</code> trait 添加到你的 <code v-pre>App\Models\User</code> 模型中。这个 trait 将为你的模型提供一些辅助方法，允许你检查经过身份验证的用户的令牌和范围：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token php language-php"><span class="token delimiter important">&lt;?php</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">namespace</span> <span class="token package">App<span class="token punctuation">\</span>Models</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Database<span class="token punctuation">\</span>Eloquent<span class="token punctuation">\</span>Factories<span class="token punctuation">\</span>HasFactory</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Foundation<span class="token punctuation">\</span>Auth<span class="token punctuation">\</span>User</span> <span class="token keyword">as</span> Authenticatable<span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Notifications<span class="token punctuation">\</span>Notifiable</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Laravel<span class="token punctuation">\</span>Passport<span class="token punctuation">\</span>HasApiTokens</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">class</span> <span class="token class-name-definition class-name">User</span> <span class="token keyword">extends</span> <span class="token class-name">Authenticatable</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">use</span> <span class="token package">HasApiTokens</span><span class="token punctuation">,</span> HasFactory<span class="token punctuation">,</span> Notifiable<span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>最后，在你的应用程序的 <code v-pre>config/auth.php</code> 配置文件中，你应该定义一个 <code v-pre>api</code> 认证守卫，并将 <code v-pre>driver</code> 选项设置为 <code v-pre>passport</code>。这将指示你的应用程序在验证传入的 API 请求时使用 Passport 的 <code v-pre>TokenGuard</code>：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token string single-quoted-string">'guards'</span> <span class="token operator">=></span> <span class="token punctuation">[</span></span>
<span class="line">    <span class="token string single-quoted-string">'web'</span> <span class="token operator">=></span> <span class="token punctuation">[</span></span>
<span class="line">        <span class="token string single-quoted-string">'driver'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'session'</span><span class="token punctuation">,</span></span>
<span class="line">        <span class="token string single-quoted-string">'provider'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'users'</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token punctuation">]</span><span class="token punctuation">,</span></span>
<span class="line"></span>
<span class="line">    <span class="token string single-quoted-string">'api'</span> <span class="token operator">=></span> <span class="token punctuation">[</span></span>
<span class="line">        <span class="token string single-quoted-string">'driver'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'passport'</span><span class="token punctuation">,</span></span>
<span class="line">        <span class="token string single-quoted-string">'provider'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'users'</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token punctuation">]</span><span class="token punctuation">,</span></span>
<span class="line"><span class="token punctuation">]</span><span class="token punctuation">,</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="部署-passport" tabindex="-1"><a class="header-anchor" href="#部署-passport"><span>部署 Passport</span></a></h3>
<p>当首次将 Passport 部署到应用程序的服务器时，你可能需要运行 <code v-pre>passport:keys</code> 命令。这个命令生成 Passport 需要的加密密钥，以便生成访问令牌。通常，生成的密钥不会保存在源代码控制中：</p>
<div class="language-bash line-numbers-mode" data-highlighter="prismjs" data-ext="sh" data-title="sh"><pre v-pre class="language-bash"><code><span class="line">php artisan passport:keys</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>如果需要，你可以定义 Passport 密钥应从哪个路径加载。你可以使用 <code v-pre>Passport::loadKeysFrom</code> 方法来实现这一点。通常情况下，这个方法应该从应用程序的 <code v-pre>App\Providers\AppServiceProvider</code> 类的 <code v-pre>boot</code> 方法中调用：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token doc-comment comment">/**</span>
<span class="line"> * 引导任何应用服务。</span>
<span class="line"> */</span></span>
<span class="line"><span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">boot</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token keyword return-type">void</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token class-name static-context">Passport</span><span class="token operator">::</span><span class="token function">loadKeysFrom</span><span class="token punctuation">(</span><span class="token constant">__DIR__</span><span class="token operator">.</span><span class="token string single-quoted-string">'/../secrets/oauth'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h4 id="从环境加载密钥" tabindex="-1"><a class="header-anchor" href="#从环境加载密钥"><span>从环境加载密钥</span></a></h4>
<p>或者，你可以使用 <code v-pre>vendor:publish</code> Artisan 命令发布 Passport 的配置文件：</p>
<div class="language-bash line-numbers-mode" data-highlighter="prismjs" data-ext="sh" data-title="sh"><pre v-pre class="language-bash"><code><span class="line">php artisan vendor:publish <span class="token parameter variable">--tag</span><span class="token operator">=</span>passport-config</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>配置文件发布后，你可以将应用程序的加密密钥定义为环境变量来加载：</p>
<div class="language-ini line-numbers-mode" data-highlighter="prismjs" data-ext="ini" data-title="ini"><pre v-pre class="language-ini"><code><span class="line"><span class="token key attr-name">PASSPORT_PRIVATE_KEY</span><span class="token punctuation">=</span><span class="token value attr-value">"-----BEGIN RSA PRIVATE KEY-----</span></span>
<span class="line">&lt;private key here></span>
<span class="line">-----END RSA PRIVATE KEY-----"</span>
<span class="line"></span>
<span class="line"><span class="token key attr-name">PASSPORT_PUBLIC_KEY</span><span class="token punctuation">=</span><span class="token value attr-value">"-----BEGIN PUBLIC KEY-----</span></span>
<span class="line">&lt;public key here></span>
<span class="line">-----END PUBLIC KEY-----"</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="升级-passport" tabindex="-1"><a class="header-anchor" href="#升级-passport"><span>升级 Passport</span></a></h3>
<p>升级到 Passport 的新主要版本时，重要的是仔细查阅<a href="https://github.com/laravel/passport/blob/master/UPGRADE.md" target="_blank" rel="noopener noreferrer">升级指南</a>。</p>
<h2 id="配置" tabindex="-1"><a class="header-anchor" href="#配置"><span>配置</span></a></h2>
<h3 id="客户端密钥哈希" tabindex="-1"><a class="header-anchor" href="#客户端密钥哈希"><span>客户端密钥哈希</span></a></h3>
<p>如果希望在数据库中存储客户端密钥时对其进行哈希处理，你应该在 <code v-pre>App\Providers\AppServiceProvider</code> 类的 <code v-pre>boot</code> 方法中调用 <code v-pre>Passport::hashClientSecrets</code> 方法：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">use</span> <span class="token package">Laravel<span class="token punctuation">\</span>Passport<span class="token punctuation">\</span>Passport</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token class-name static-context">Passport</span><span class="token operator">::</span><span class="token function">hashClientSecrets</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>启用后，所有客户端密钥只能在创建后立即显示给用户。由于明文客户端密钥值从不存储在数据库中，如果丢失，则无法恢复密钥的值。</p>
<h3 id="令牌生命周期" tabindex="-1"><a class="header-anchor" href="#令牌生命周期"><span>令牌生命周期</span></a></h3>
<p>默认情况下，Passport发放的访问令牌具有长期有效性，在一年后过期。如果你想配置更长/更短的令牌生命周期，你可以使用 <code v-pre>tokensExpireIn</code>、<code v-pre>refreshTokensExpireIn</code> 和 <code v-pre>personalAccessTokensExpireIn</code> 方法。这些方法应该从应用程序的 <code v-pre>App\Providers\AppServiceProvider</code> 类的 <code v-pre>boot</code> 方法中调用：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token doc-comment comment">/**</span>
<span class="line"> * 引导任何应用服务。</span>
<span class="line"> */</span></span>
<span class="line"><span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">boot</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token keyword return-type">void</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token class-name static-context">Passport</span><span class="token operator">::</span><span class="token function">tokensExpireIn</span><span class="token punctuation">(</span><span class="token function">now</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">addDays</span><span class="token punctuation">(</span><span class="token number">15</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token class-name static-context">Passport</span><span class="token operator">::</span><span class="token function">refreshTokensExpireIn</span><span class="token punctuation">(</span><span class="token function">now</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">addDays</span><span class="token punctuation">(</span><span class="token number">30</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token class-name static-context">Passport</span><span class="token operator">::</span><span class="token function">personalAccessTokensExpireIn</span><span class="token punctuation">(</span><span class="token function">now</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">addMonths</span><span class="token punctuation">(</span><span class="token number">6</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><blockquote>
<p><strong>警告</strong><br>
Passport数据库表上的<code v-pre>expires_at</code>列是只读的，仅用于显示目的。在发放令牌时，Passport会将过期信息存储在签名和加密令牌中。如果需要使令牌失效，你应该<a href="#revoking-tokens">撤销它</a>。</p>
</blockquote>
<h3 id="覆盖默认模型" tabindex="-1"><a class="header-anchor" href="#覆盖默认模型"><span>覆盖默认模型</span></a></h3>
<p>你可以通过定义自己的模型并扩展相应的Passport模型来自由扩展Passport内部使用的模型：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">use</span> <span class="token package">Laravel<span class="token punctuation">\</span>Passport<span class="token punctuation">\</span>Client</span> <span class="token keyword">as</span> PassportClient<span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">class</span> <span class="token class-name-definition class-name">Client</span> <span class="token keyword">extends</span> <span class="token class-name">PassportClient</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token comment">// ...</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>定义完你的模型后，你可以通过<code v-pre>Laravel\Passport\Passport</code>类指示Passport使用你的自定义模型。通常情况下，你应该在应用程序的<code v-pre>App\Providers\AppServiceProvider</code>类的<code v-pre>boot</code>方法中告知Passport有关你的自定义模型：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">use</span> <span class="token package">App<span class="token punctuation">\</span>Models<span class="token punctuation">\</span>Passport<span class="token punctuation">\</span>AuthCode</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">App<span class="token punctuation">\</span>Models<span class="token punctuation">\</span>Passport<span class="token punctuation">\</span>Client</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">App<span class="token punctuation">\</span>Models<span class="token punctuation">\</span>Passport<span class="token punctuation">\</span>PersonalAccessClient</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">App<span class="token punctuation">\</span>Models<span class="token punctuation">\</span>Passport<span class="token punctuation">\</span>RefreshToken</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">App<span class="token punctuation">\</span>Models<span class="token punctuation">\</span>Passport<span class="token punctuation">\</span>Token</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token doc-comment comment">/**</span>
<span class="line"> * 引导任何应用服务。</span>
<span class="line"> */</span></span>
<span class="line"><span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">boot</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token keyword return-type">void</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token class-name static-context">Passport</span><span class="token operator">::</span><span class="token function">useTokenModel</span><span class="token punctuation">(</span><span class="token class-name static-context">Token</span><span class="token operator">::</span><span class="token keyword">class</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token class-name static-context">Passport</span><span class="token operator">::</span><span class="token function">useRefreshTokenModel</span><span class="token punctuation">(</span><span class="token class-name static-context">RefreshToken</span><span class="token operator">::</span><span class="token keyword">class</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token class-name static-context">Passport</span><span class="token operator">::</span><span class="token function">useAuthCodeModel</span><span class="token punctuation">(</span><span class="token class-name static-context">AuthCode</span><span class="token operator">::</span><span class="token keyword">class</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token class-name static-context">Passport</span><span class="token operator">::</span><span class="token function">useClientModel</span><span class="token punctuation">(</span><span class="token class-name static-context">Client</span><span class="token operator">::</span><span class="token keyword">class</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token class-name static-context">Passport</span><span class="token operator">::</span><span class="token function">usePersonalAccessClientModel</span><span class="token punctuation">(</span><span class="token class-name static-context">PersonalAccessClient</span><span class="token operator">::</span><span class="token keyword">class</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="覆盖路由" tabindex="-1"><a class="header-anchor" href="#覆盖路由"><span>覆盖路由</span></a></h3>
<p>有时你可能希望自定义Passport定义的路由。为实现此目的，首先需要在应用程序的 <code v-pre>AppServiceProvider</code> 的 <code v-pre>register</code> 方法中添加 <code v-pre>Passport::ignoreRoutes</code> 来忽略Passport注册的路由：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">use</span> <span class="token package">Laravel<span class="token punctuation">\</span>Passport<span class="token punctuation">\</span>Passport</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token doc-comment comment">/**</span>
<span class="line"> * 注册任何应用服务。</span>
<span class="line"> */</span></span>
<span class="line"><span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">register</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token keyword return-type">void</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token class-name static-context">Passport</span><span class="token operator">::</span><span class="token function">ignoreRoutes</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>然后，你可以将Passport在<a href="https://github.com/laravel/passport/blob/11.x/routes/web.php" target="_blank" rel="noopener noreferrer">其路由文件</a>中定义的路由复制到你的应用程序的 <code v-pre>routes/web.php</code> 文件中，并根据需要进行修改：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token class-name static-context">Route</span><span class="token operator">::</span><span class="token function">group</span><span class="token punctuation">(</span><span class="token punctuation">[</span></span>
<span class="line">    <span class="token string single-quoted-string">'as'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'passport.'</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token string single-quoted-string">'prefix'</span> <span class="token operator">=></span> <span class="token function">config</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'passport.path'</span><span class="token punctuation">,</span> <span class="token string single-quoted-string">'oauth'</span><span class="token punctuation">)</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token string single-quoted-string">'namespace'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'\Laravel\Passport\Http\Controllers'</span><span class="token punctuation">,</span></span>
<span class="line"><span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token comment">// Passport routes...</span></span>
<span class="line"><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h2 id="发放访问令牌" tabindex="-1"><a class="header-anchor" href="#发放访问令牌"><span>发放访问令牌</span></a></h2>
<p>通过授权码使用OAuth2是大多数开发人员熟悉的OAuth2方式。在使用授权码时，客户端应用程序将用户重定向到你的服务器，在那里用户将批准或拒绝向客户端发放访问令牌的请求。</p>
<h3 id="管理客户端" tabindex="-1"><a class="header-anchor" href="#管理客户端"><span>管理客户端</span></a></h3>
<p>首先，需要与需要与你的应用程序API交互的应用程序开发人员注册他们的应用程序，创建一个“客户端”。通常，这包括提供他们应用程序的名称和一个URL，你的应用程序可以在用户批准他们的授权请求后重定向到该URL。</p>
<h4 id="passport-client-命令" tabindex="-1"><a class="header-anchor" href="#passport-client-命令"><span><code v-pre>passport:client</code> 命令</span></a></h4>
<p>创建客户端的最简单方法是使用 <code v-pre>passport:client</code> Artisan 命令。此命令可用于为测试你的OAuth2功能创建自己的客户端。当运行 <code v-pre>client</code> 命令时，Passport将提示你提供有关你的客户端的更多信息，并为你提供客户端ID和密钥：</p>
<div class="language-bash line-numbers-mode" data-highlighter="prismjs" data-ext="sh" data-title="sh"><pre v-pre class="language-bash"><code><span class="line">php artisan passport:client</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p><strong>重定向URL</strong></p>
<p>如果你想为你的客户端允许多个重定向URL，你可以在 <code v-pre>passport:client</code> 命令提示的URL处使用逗号分隔的列表来指定它们。任何包含逗号的URL都应该进行URL编码：</p>
<div class="language-bash line-numbers-mode" data-highlighter="prismjs" data-ext="sh" data-title="sh"><pre v-pre class="language-bash"><code><span class="line">http://example.com/callback,http://examplefoo.com/callback</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><h4 id="json-api" tabindex="-1"><a class="header-anchor" href="#json-api"><span>JSON API</span></a></h4>
<p>由于你的应用程序用户无法使用 <code v-pre>client</code> 命令，Passport提供了一个JSON API，你可以用来创建客户端。这样可以避免手动编写用于创建、更新和删除客户端的控制器。</p>
<p>但是，你需要将Passport的JSON API与你自己的前端配对，为用户提供一个仪表板，让他们管理他们的客户端。下面，我们将回顾所有用于管理客户端的API端点。为了方便起见，我们将使用<a href="https://github.com/axios/axios" target="_blank" rel="noopener noreferrer">Axios</a>来演示如何向这些端点发出HTTP请求。</p>
<p>JSON API受到<code v-pre>web</code>和<code v-pre>auth</code>中间件的保护；因此，它只能从你自己的应用程序调用，无法从外部来源调用。</p>
<h4 id="get-oauth-clients" tabindex="-1"><a class="header-anchor" href="#get-oauth-clients"><span><code v-pre>GET /oauth/clients</code></span></a></h4>
<p>此路由返回经过身份验证的用户的所有客户端。这主要用于列出用户的所有客户端，以便他们可以编辑或删除它们：</p>
<div class="language-javascript line-numbers-mode" data-highlighter="prismjs" data-ext="js" data-title="js"><pre v-pre class="language-javascript"><code><span class="line">axios<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string">'/oauth/clients'</span><span class="token punctuation">)</span></span>
<span class="line">    <span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token parameter">response</span> <span class="token operator">=></span> <span class="token punctuation">{</span></span>
<span class="line">        console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>response<span class="token punctuation">.</span>data<span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h4 id="post-oauth-clients" tabindex="-1"><a class="header-anchor" href="#post-oauth-clients"><span><code v-pre>POST /oauth/clients</code></span></a></h4>
<p>此路由用于创建新的客户端。它需要两个数据：客户端的<code v-pre>name</code>和<code v-pre>redirect</code> URL。<code v-pre>redirect</code> URL是用户在批准或拒绝授权请求后将被重定向的地方。</p>
<p>当创建客户端时，将会分配一个客户端ID和客户端密钥。在从你的应用程序请求访问令牌时，将使用这些值。客户端创建路由将返回新的客户端实例：</p>
<div class="language-javascript line-numbers-mode" data-highlighter="prismjs" data-ext="js" data-title="js"><pre v-pre class="language-javascript"><code><span class="line"><span class="token keyword">const</span> data <span class="token operator">=</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token literal-property property">name</span><span class="token operator">:</span> <span class="token string">'客户端名称'</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token literal-property property">redirect</span><span class="token operator">:</span> <span class="token string">'http://example.com/callback'</span></span>
<span class="line"><span class="token punctuation">}</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">axios<span class="token punctuation">.</span><span class="token function">post</span><span class="token punctuation">(</span><span class="token string">'/oauth/clients'</span><span class="token punctuation">,</span> data<span class="token punctuation">)</span></span>
<span class="line">    <span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token parameter">response</span> <span class="token operator">=></span> <span class="token punctuation">{</span></span>
<span class="line">        console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>response<span class="token punctuation">.</span>data<span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token punctuation">}</span><span class="token punctuation">)</span></span>
<span class="line">    <span class="token punctuation">.</span><span class="token function">catch</span><span class="token punctuation">(</span><span class="token parameter">response</span> <span class="token operator">=></span> <span class="token punctuation">{</span></span>
<span class="line">        <span class="token comment">// 在响应中列出错误...</span></span>
<span class="line">    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h4 id="put-oauth-clients-client-id" tabindex="-1"><a class="header-anchor" href="#put-oauth-clients-client-id"><span><code v-pre>PUT /oauth/clients/{client-id}</code></span></a></h4>
<p>此路由用于更新客户端。它需要两个数据：客户端的<code v-pre>name</code>和<code v-pre>redirect</code> URL。<code v-pre>redirect</code> URL是用户在批准或拒绝授权请求后将被重定向的地方。路由将返回更新后的客户端实例：</p>
<div class="language-javascript line-numbers-mode" data-highlighter="prismjs" data-ext="js" data-title="js"><pre v-pre class="language-javascript"><code><span class="line"><span class="token keyword">const</span> data <span class="token operator">=</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token literal-property property">name</span><span class="token operator">:</span> <span class="token string">'新的客户端名称'</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token literal-property property">redirect</span><span class="token operator">:</span> <span class="token string">'http://example.com/callback'</span></span>
<span class="line"><span class="token punctuation">}</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">axios<span class="token punctuation">.</span><span class="token function">put</span><span class="token punctuation">(</span><span class="token string">'/oauth/clients/'</span> <span class="token operator">+</span> clientId<span class="token punctuation">,</span> data<span class="token punctuation">)</span></span>
<span class="line">    <span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token parameter">response</span> <span class="token operator">=></span> <span class="token punctuation">{</span></span>
<span class="line">        console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>response<span class="token punctuation">.</span>data<span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token punctuation">}</span><span class="token punctuation">)</span></span>
<span class="line">    <span class="token punctuation">.</span><span class="token function">catch</span><span class="token punctuation">(</span><span class="token parameter">response</span> <span class="token operator">=></span> <span class="token punctuation">{</span></span>
<span class="line">        <span class="token comment">// 在响应中列出错误...</span></span>
<span class="line">    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h4 id="delete-oauth-clients-client-id" tabindex="-1"><a class="header-anchor" href="#delete-oauth-clients-client-id"><span><code v-pre>DELETE /oauth/clients/{client-id}</code></span></a></h4>
<p>此路由用于删除客户端：</p>
<div class="language-javascript line-numbers-mode" data-highlighter="prismjs" data-ext="js" data-title="js"><pre v-pre class="language-javascript"><code><span class="line">axios<span class="token punctuation">.</span><span class="token function">delete</span><span class="token punctuation">(</span><span class="token string">'/oauth/clients/'</span> <span class="token operator">+</span> clientId<span class="token punctuation">)</span></span>
<span class="line">    <span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token parameter">response</span> <span class="token operator">=></span> <span class="token punctuation">{</span></span>
<span class="line">        <span class="token comment">// ...</span></span>
<span class="line">    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="请求令牌" tabindex="-1"><a class="header-anchor" href="#请求令牌"><span>请求令牌</span></a></h3>
<h4 id="重定向进行授权" tabindex="-1"><a class="header-anchor" href="#重定向进行授权"><span>重定向进行授权</span></a></h4>
<p>一旦创建了客户端，开发人员可以使用他们的客户端ID和密钥从你的应用程序请求授权码和访问令牌。首先，消费应用程序应该向你的应用程序的 <code v-pre>/oauth/authorize</code> 路由发起重定向请求，如下所示：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Http<span class="token punctuation">\</span>Request</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Support<span class="token punctuation">\</span>Str</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token class-name static-context">Route</span><span class="token operator">::</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'/redirect'</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token class-name type-declaration">Request</span> <span class="token variable">$request</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token variable">$request</span><span class="token operator">-></span><span class="token function">session</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">put</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'state'</span><span class="token punctuation">,</span> <span class="token variable">$state</span> <span class="token operator">=</span> <span class="token class-name static-context">Str</span><span class="token operator">::</span><span class="token function">random</span><span class="token punctuation">(</span><span class="token number">40</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">    <span class="token variable">$query</span> <span class="token operator">=</span> <span class="token function">http_build_query</span><span class="token punctuation">(</span><span class="token punctuation">[</span></span>
<span class="line">        <span class="token string single-quoted-string">'client_id'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'client-id'</span><span class="token punctuation">,</span></span>
<span class="line">        <span class="token string single-quoted-string">'redirect_uri'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'http://third-party-app.com/callback'</span><span class="token punctuation">,</span></span>
<span class="line">        <span class="token string single-quoted-string">'response_type'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'code'</span><span class="token punctuation">,</span></span>
<span class="line">        <span class="token string single-quoted-string">'scope'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">''</span><span class="token punctuation">,</span></span>
<span class="line">        <span class="token string single-quoted-string">'state'</span> <span class="token operator">=></span> <span class="token variable">$state</span><span class="token punctuation">,</span></span>
<span class="line">        <span class="token comment">// 'prompt' => '', // "none", "consent", or "login"</span></span>
<span class="line">    <span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">    <span class="token keyword">return</span> <span class="token function">redirect</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'http://passport-app.test/oauth/authorize?'</span> <span class="token operator">.</span> <span class="token variable">$query</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><code v-pre>prompt</code>参数可用于指定Passport应用程序的身份验证行为。</p>
<p>如果<code v-pre>prompt</code>值为<code v-pre>none</code>，如果用户尚未通过Passport应用程序进行身份验证，Passport将始终抛出身份验证错误。如果值为<code v-pre>consent</code>，Passport将始终显示授权批准屏幕，即使所有权限之前已经授予给消费应用程序。当值为<code v-pre>login</code>时，Passport应用程序将始终提示用户重新登录应用程序，即使他们已经有一个现有会话。</p>
<p>如果未提供<code v-pre>prompt</code>值，则仅当用户之前未授权访问请求的范围时，用户将被提示进行授权。</p>
<blockquote>
<p><strong>注意</strong><br>
请记住，<code v-pre>/oauth/authorize</code>路由已经由Passport定义。你不需要手动定义这个路由。</p>
</blockquote>
<h4 id="批准请求" tabindex="-1"><a class="header-anchor" href="#批准请求"><span>批准请求</span></a></h4>
<p>在接收授权请求时，Passport将根据<code v-pre>prompt</code>参数的值（如果存在）自动做出响应，并可能向用户显示一个模板，让他们批准或拒绝授权请求。如果他们批准请求，他们将被重定向回消费应用程序指定的<code v-pre>redirect_uri</code>。<code v-pre>redirect_uri</code>必须与创建客户端时指定的<code v-pre>redirect</code> URL匹配。</p>
<p>如果你想自定义授权批准屏幕，你可以使用<code v-pre>vendor:publish</code> Artisan命令发布Passport的视图。发布的视图将放置在<code v-pre>resources/views/vendor/passport</code>目录中：</p>
<div class="language-bash line-numbers-mode" data-highlighter="prismjs" data-ext="sh" data-title="sh"><pre v-pre class="language-bash"><code><span class="line">php artisan vendor:publish <span class="token parameter variable">--tag</span><span class="token operator">=</span>passport-views</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>有时你可能希望跳过授权提示，比如在授权第一方客户端时。你可以通过<a href="#overriding-default-models">扩展<code v-pre>Client</code>模型</a>并定义一个<code v-pre>skipsAuthorization</code>方法来实现这一点。如果<code v-pre>skipsAuthorization</code>返回<code v-pre>true</code>，客户端将被批准，并且用户将立即被重定向回<code v-pre>redirect_uri</code>，除非消费应用程序在重定向授权时明确设置了<code v-pre>prompt</code>参数：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token php language-php"><span class="token delimiter important">&lt;?php</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">namespace</span> <span class="token package">App<span class="token punctuation">\</span>Models<span class="token punctuation">\</span>Passport</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Laravel<span class="token punctuation">\</span>Passport<span class="token punctuation">\</span>Client</span> <span class="token keyword">as</span> BaseClient<span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">class</span> <span class="token class-name-definition class-name">Client</span> <span class="token keyword">extends</span> <span class="token class-name">BaseClient</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token doc-comment comment">/**</span>
<span class="line">     * Determine if the client should skip the authorization prompt.</span>
<span class="line">     */</span></span>
<span class="line">    <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">skipsAuthorization</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token keyword return-type">bool</span></span>
<span class="line">    <span class="token punctuation">{</span></span>
<span class="line">        <span class="token keyword">return</span> <span class="token variable">$this</span><span class="token operator">-></span><span class="token function">firstParty</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token punctuation">}</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h4 id="将授权码转换为访问令牌" tabindex="-1"><a class="header-anchor" href="#将授权码转换为访问令牌"><span>将授权码转换为访问令牌</span></a></h4>
<p>如果用户批准授权请求，他们将被重定向回消费应用程序。消费者应首先根据重定向前存储的值验证<code v-pre>state</code>参数。如果state参数匹配，则消费者应发出<code v-pre>POST</code>请求到你的应用程序请求访问令牌。请求应包括用户批准授权请求时你的应用程序发放的授权码：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Http<span class="token punctuation">\</span>Request</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Support<span class="token punctuation">\</span>Facades<span class="token punctuation">\</span>Http</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token class-name static-context">Route</span><span class="token operator">::</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'/callback'</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token class-name type-declaration">Request</span> <span class="token variable">$request</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token variable">$state</span> <span class="token operator">=</span> <span class="token variable">$request</span><span class="token operator">-></span><span class="token function">session</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">pull</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'state'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">    <span class="token function">throw_unless</span><span class="token punctuation">(</span></span>
<span class="line">        <span class="token function">strlen</span><span class="token punctuation">(</span><span class="token variable">$state</span><span class="token punctuation">)</span> <span class="token operator">></span> <span class="token number">0</span> <span class="token operator">&amp;&amp;</span> <span class="token variable">$state</span> <span class="token operator">===</span> <span class="token variable">$request</span><span class="token operator">-></span><span class="token property">state</span><span class="token punctuation">,</span></span>
<span class="line">        <span class="token class-name static-context">InvalidArgumentException</span><span class="token operator">::</span><span class="token keyword">class</span><span class="token punctuation">,</span></span>
<span class="line">        <span class="token string single-quoted-string">'Invalid state value.'</span></span>
<span class="line">    <span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">    <span class="token variable">$response</span> <span class="token operator">=</span> <span class="token class-name static-context">Http</span><span class="token operator">::</span><span class="token function">asForm</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">post</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'http://passport-app.test/oauth/token'</span><span class="token punctuation">,</span> <span class="token punctuation">[</span></span>
<span class="line">        <span class="token string single-quoted-string">'grant_type'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'authorization_code'</span><span class="token punctuation">,</span></span>
<span class="line">        <span class="token string single-quoted-string">'client_id'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'client-id'</span><span class="token punctuation">,</span></span>
<span class="line">        <span class="token string single-quoted-string">'client_secret'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'client-secret'</span><span class="token punctuation">,</span></span>
<span class="line">        <span class="token string single-quoted-string">'redirect_uri'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'http://third-party-app.com/callback'</span><span class="token punctuation">,</span></span>
<span class="line">        <span class="token string single-quoted-string">'code'</span> <span class="token operator">=></span> <span class="token variable">$request</span><span class="token operator">-></span><span class="token property">code</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">    <span class="token keyword">return</span> <span class="token variable">$response</span><span class="token operator">-></span><span class="token function">json</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>这个<code v-pre>/oauth/token</code>路由将返回一个包含<code v-pre>access_token</code>、<code v-pre>refresh_token</code>和<code v-pre>expires_in</code>属性的JSON响应。<code v-pre>expires_in</code>属性包含访问令牌过期前的秒数。</p>
<blockquote>
<p><strong>注意</strong><br>
像<code v-pre>/oauth/authorize</code>路由一样，<code v-pre>/oauth/token</code>路由由Passport为你定义。你不需要手动定义这个路由。</p>
</blockquote>
<h4 id="json-api-1" tabindex="-1"><a class="header-anchor" href="#json-api-1"><span>JSON API</span></a></h4>
<p>Passport还包括一个用于管理授权访问令牌的JSON API。你可以将其与自己的前端配对，为用户提供一个管理访问令牌的仪表板。为了方便起见，我们将使用<a href="https://github.com/mzabriskie/axios" target="_blank" rel="noopener noreferrer">Axios</a>来演示如何向端点发出HTTP请求。JSON API受<code v-pre>web</code>和<code v-pre>auth</code>中间件保护；因此，它只能从你自己的应用程序中调用。</p>
<h4 id="get-oauth-tokens" tabindex="-1"><a class="header-anchor" href="#get-oauth-tokens"><span><code v-pre>GET /oauth/tokens</code></span></a></h4>
<p>这个路由返回经过授权的所有访问令牌，这些令牌是认证用户创建的。这主要用于列出用户的所有令牌，以便他们可以撤销它们：</p>
<div class="language-javascript line-numbers-mode" data-highlighter="prismjs" data-ext="js" data-title="js"><pre v-pre class="language-javascript"><code><span class="line">axios<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string">'/oauth/tokens'</span><span class="token punctuation">)</span></span>
<span class="line">    <span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token parameter">response</span> <span class="token operator">=></span> <span class="token punctuation">{</span></span>
<span class="line">        console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>response<span class="token punctuation">.</span>data<span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h4 id="delete-oauth-tokens-token-id" tabindex="-1"><a class="header-anchor" href="#delete-oauth-tokens-token-id"><span><code v-pre>DELETE /oauth/tokens/{token-id}</code></span></a></h4>
<p>这个路由可用于撤销经过授权的访问令牌及其相关的刷新令牌：</p>
<div class="language-javascript line-numbers-mode" data-highlighter="prismjs" data-ext="js" data-title="js"><pre v-pre class="language-javascript"><code><span class="line">axios<span class="token punctuation">.</span><span class="token function">delete</span><span class="token punctuation">(</span><span class="token string">'/oauth/tokens/'</span> <span class="token operator">+</span> tokenId<span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><h3 id="刷新令牌" tabindex="-1"><a class="header-anchor" href="#刷新令牌"><span>刷新令牌</span></a></h3>
<p>如果你的应用程序发放短期访问令牌，用户将需要通过在发放访问令牌时提供的刷新令牌来刷新他们的访问令牌：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Support<span class="token punctuation">\</span>Facades<span class="token punctuation">\</span>Http</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token variable">$response</span> <span class="token operator">=</span> <span class="token class-name static-context">Http</span><span class="token operator">::</span><span class="token function">asForm</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">post</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'http://passport-app.test/oauth/token'</span><span class="token punctuation">,</span> <span class="token punctuation">[</span></span>
<span class="line">    <span class="token string single-quoted-string">'grant_type'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'refresh_token'</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token string single-quoted-string">'refresh_token'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'the-refresh-token'</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token string single-quoted-string">'client_id'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'client-id'</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token string single-quoted-string">'client_secret'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'client-secret'</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token string single-quoted-string">'scope'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">''</span><span class="token punctuation">,</span></span>
<span class="line"><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">return</span> <span class="token variable">$response</span><span class="token operator">-></span><span class="token function">json</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>这个<code v-pre>/oauth/token</code>路由将返回一个包含<code v-pre>access_token</code>、<code v-pre>refresh_token</code>和<code v-pre>expires_in</code>属性的JSON响应。<code v-pre>expires_in</code>属性包含访问令牌过期前的秒数。</p>
<h3 id="撤销令牌" tabindex="-1"><a class="header-anchor" href="#撤销令牌"><span>撤销令牌</span></a></h3>
<p>你可以使用<code v-pre>Laravel\Passport\TokenRepository</code>上的<code v-pre>revokeAccessToken</code>方法来撤销一个令牌。你可以使用<code v-pre>Laravel\Passport\RefreshTokenRepository</code>上的<code v-pre>revokeRefreshTokensByAccessTokenId</code>方法来撤销一个令牌的刷新令牌。这些类可以通过Laravel的<a href="https://learnku.com/docs/laravel/11.x/container" target="_blank" rel="noopener noreferrer">服务容器</a>来解析：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">use</span> <span class="token package">Laravel<span class="token punctuation">\</span>Passport<span class="token punctuation">\</span>TokenRepository</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Laravel<span class="token punctuation">\</span>Passport<span class="token punctuation">\</span>RefreshTokenRepository</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token variable">$tokenRepository</span> <span class="token operator">=</span> <span class="token function">app</span><span class="token punctuation">(</span><span class="token class-name static-context">TokenRepository</span><span class="token operator">::</span><span class="token keyword">class</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token variable">$refreshTokenRepository</span> <span class="token operator">=</span> <span class="token function">app</span><span class="token punctuation">(</span><span class="token class-name static-context">RefreshTokenRepository</span><span class="token operator">::</span><span class="token keyword">class</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token comment">// 撤销一个访问令牌...</span></span>
<span class="line"><span class="token variable">$tokenRepository</span><span class="token operator">-></span><span class="token function">revokeAccessToken</span><span class="token punctuation">(</span><span class="token variable">$tokenId</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token comment">// 撤销所有令牌的刷新令牌...</span></span>
<span class="line"><span class="token variable">$refreshTokenRepository</span><span class="token operator">-></span><span class="token function">revokeRefreshTokensByAccessTokenId</span><span class="token punctuation">(</span><span class="token variable">$tokenId</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="清理令牌" tabindex="-1"><a class="header-anchor" href="#清理令牌"><span>清理令牌</span></a></h3>
<p>当令牌被撤销或过期时，你可能希望从数据库中清除它们。Passport附带的<code v-pre>passport:purge</code> Artisan命令可以帮助你实现这一点：</p>
<div class="language-bash line-numbers-mode" data-highlighter="prismjs" data-ext="sh" data-title="sh"><pre v-pre class="language-bash"><code><span class="line"><span class="token comment"># 清除被撤销和过期的令牌和授权码...</span></span>
<span class="line">php artisan passport:purge</span>
<span class="line"></span>
<span class="line"><span class="token comment"># 仅清除超过6小时过期的令牌...</span></span>
<span class="line">php artisan passport:purge <span class="token parameter variable">--hours</span><span class="token operator">=</span><span class="token number">6</span></span>
<span class="line"></span>
<span class="line"><span class="token comment"># 仅清除被撤销的令牌和授权码...</span></span>
<span class="line">php artisan passport:purge <span class="token parameter variable">--revoked</span></span>
<span class="line"></span>
<span class="line"><span class="token comment"># 仅清除过期的令牌和授权码...</span></span>
<span class="line">php artisan passport:purge <span class="token parameter variable">--expired</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>你还可以在应用程序的<code v-pre>routes/console.php</code>文件中配置一个<a href="https://learnku.com/docs/laravel/11.x/scheduling" target="_blank" rel="noopener noreferrer">定时任务</a>，以便在计划时间自动清理你的令牌：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">use</span> <span class="token package">Laravel<span class="token punctuation">\</span>Support<span class="token punctuation">\</span>Facades<span class="token punctuation">\</span>Schedule</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token class-name static-context">Schedule</span><span class="token operator">::</span><span class="token function">command</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'passport:purge'</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">hourly</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h2 id="使用pkce的授权码授予" tabindex="-1"><a class="header-anchor" href="#使用pkce的授权码授予"><span>使用PKCE的授权码授予</span></a></h2>
<p>具有「Proof Key for Code Exchange」（PKCE）的授权码授予是一种安全的方式，用于验证单页应用程序或原生应用程序以访问你的API。当无法保证客户端密钥会被保密存储，或者为了减轻授权码被攻击者拦截的威胁时，应使用这种授权方式。在交换授权码获取访问令牌时，一个“代码验证器”和一个“代码挑战”组合取代了客户端密钥。</p>
<h3 id="创建客户端" tabindex="-1"><a class="header-anchor" href="#创建客户端"><span>创建客户端</span></a></h3>
<p>在你的应用程序可以通过带有PKCE的授权码授予发放令牌之前，你需要创建一个启用了PKCE的客户端。你可以使用<code v-pre>passport:client</code> Artisan命令并加上<code v-pre>--public</code>选项来实现：</p>
<div class="language-bash line-numbers-mode" data-highlighter="prismjs" data-ext="sh" data-title="sh"><pre v-pre class="language-bash"><code><span class="line">php artisan passport:client <span class="token parameter variable">--public</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><h3 id="请求令牌-1" tabindex="-1"><a class="header-anchor" href="#请求令牌-1"><span>请求令牌</span></a></h3>
<h4 id="代码验证器和代码挑战" tabindex="-1"><a class="header-anchor" href="#代码验证器和代码挑战"><span>代码验证器和代码挑战</span></a></h4>
<p>由于这种授权方式不提供客户端密钥，开发人员需要生成一个代码验证器和一个代码挑战的组合来请求令牌。</p>
<p>代码验证器应该是一个包含字母、数字和<code v-pre>&quot;-&quot;</code>、<code v-pre>&quot;.&quot;</code>、<code v-pre>&quot;_&quot;</code>、<code v-pre>&quot;~&quot;</code>字符的随机字符串，长度在43到128个字符之间，如<a href="https://tools.ietf.org/html/rfc7636" target="_blank" rel="noopener noreferrer">RFC 7636规范</a>中定义。</p>
<p>代码挑战应该是一个使用Base64编码的字符串，其中包含URL和文件名安全字符。末尾的<code v-pre>'='</code>字符应该被移除，不应包含换行、空格或其他额外字符。</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token variable">$encoded</span> <span class="token operator">=</span> <span class="token function">base64_encode</span><span class="token punctuation">(</span><span class="token function">hash</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'sha256'</span><span class="token punctuation">,</span> <span class="token variable">$code_verifier</span><span class="token punctuation">,</span> <span class="token constant boolean">true</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token variable">$codeChallenge</span> <span class="token operator">=</span> <span class="token function">strtr</span><span class="token punctuation">(</span><span class="token function">rtrim</span><span class="token punctuation">(</span><span class="token variable">$encoded</span><span class="token punctuation">,</span> <span class="token string single-quoted-string">'='</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token string single-quoted-string">'+/'</span><span class="token punctuation">,</span> <span class="token string single-quoted-string">'-_'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h4 id="重定向进行授权-1" tabindex="-1"><a class="header-anchor" href="#重定向进行授权-1"><span>重定向进行授权</span></a></h4>
<p>一旦客户端被创建，你可以使用客户端ID以及生成的代码验证器和代码挑战来从你的应用程序请求授权码和访问令牌。首先，消费应用程序应该向你的应用程序的<code v-pre>/oauth/authorize</code>路由发出重定向请求：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Http<span class="token punctuation">\</span>Request</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Support<span class="token punctuation">\</span>Str</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token class-name static-context">Route</span><span class="token operator">::</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'/redirect'</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token class-name type-declaration">Request</span> <span class="token variable">$request</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token variable">$request</span><span class="token operator">-></span><span class="token function">session</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">put</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'state'</span><span class="token punctuation">,</span> <span class="token variable">$state</span> <span class="token operator">=</span> <span class="token class-name static-context">Str</span><span class="token operator">::</span><span class="token function">random</span><span class="token punctuation">(</span><span class="token number">40</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">    <span class="token variable">$request</span><span class="token operator">-></span><span class="token function">session</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">put</span><span class="token punctuation">(</span></span>
<span class="line">        <span class="token string single-quoted-string">'code_verifier'</span><span class="token punctuation">,</span> <span class="token variable">$code_verifier</span> <span class="token operator">=</span> <span class="token class-name static-context">Str</span><span class="token operator">::</span><span class="token function">random</span><span class="token punctuation">(</span><span class="token number">128</span><span class="token punctuation">)</span></span>
<span class="line">    <span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">    <span class="token variable">$codeChallenge</span> <span class="token operator">=</span> <span class="token function">strtr</span><span class="token punctuation">(</span><span class="token function">rtrim</span><span class="token punctuation">(</span></span>
<span class="line">        <span class="token function">base64_encode</span><span class="token punctuation">(</span><span class="token function">hash</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'sha256'</span><span class="token punctuation">,</span> <span class="token variable">$code_verifier</span><span class="token punctuation">,</span> <span class="token constant boolean">true</span><span class="token punctuation">)</span><span class="token punctuation">)</span></span>
<span class="line">    <span class="token punctuation">,</span> <span class="token string single-quoted-string">'='</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token string single-quoted-string">'+/'</span><span class="token punctuation">,</span> <span class="token string single-quoted-string">'-_'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">    <span class="token variable">$query</span> <span class="token operator">=</span> <span class="token function">http_build_query</span><span class="token punctuation">(</span><span class="token punctuation">[</span></span>
<span class="line">        <span class="token string single-quoted-string">'client_id'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'client-id'</span><span class="token punctuation">,</span></span>
<span class="line">        <span class="token string single-quoted-string">'redirect_uri'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'http://third-party-app.com/callback'</span><span class="token punctuation">,</span></span>
<span class="line">        <span class="token string single-quoted-string">'response_type'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'code'</span><span class="token punctuation">,</span></span>
<span class="line">        <span class="token string single-quoted-string">'scope'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">''</span><span class="token punctuation">,</span></span>
<span class="line">        <span class="token string single-quoted-string">'state'</span> <span class="token operator">=></span> <span class="token variable">$state</span><span class="token punctuation">,</span></span>
<span class="line">        <span class="token string single-quoted-string">'code_challenge'</span> <span class="token operator">=></span> <span class="token variable">$codeChallenge</span><span class="token punctuation">,</span></span>
<span class="line">        <span class="token string single-quoted-string">'code_challenge_method'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'S256'</span><span class="token punctuation">,</span></span>
<span class="line">        <span class="token comment">// 'prompt' => '', // "none", "consent", or "login"</span></span>
<span class="line">    <span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">    <span class="token keyword">return</span> <span class="token function">redirect</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'http://passport-app.test/oauth/authorize?'</span> <span class="token operator">.</span> <span class="token variable">$query</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h4 id="将授权码转换为访问令牌-1" tabindex="-1"><a class="header-anchor" href="#将授权码转换为访问令牌-1"><span>将授权码转换为访问令牌</span></a></h4>
<p>如果用户批准授权请求，他们将被重定向回消费应用程序。消费者应该根据重定向前存储的值验证<code v-pre>state</code>参数，就像标准的授权码授予方式一样。</p>
<p>如果state参数匹配，消费者应该向你的应用程序发出<code v-pre>POST</code>请求来请求一个访问令牌。请求应该包括用户批准授权请求时你的应用程序发放的授权码，以及最初生成的代码验证器：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Http<span class="token punctuation">\</span>Request</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Support<span class="token punctuation">\</span>Facades<span class="token punctuation">\</span>Http</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token class-name static-context">Route</span><span class="token operator">::</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'/callback'</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token class-name type-declaration">Request</span> <span class="token variable">$request</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token variable">$state</span> <span class="token operator">=</span> <span class="token variable">$request</span><span class="token operator">-></span><span class="token function">session</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">pull</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'state'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">    <span class="token variable">$codeVerifier</span> <span class="token operator">=</span> <span class="token variable">$request</span><span class="token operator">-></span><span class="token function">session</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">pull</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'code_verifier'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">    <span class="token function">throw_unless</span><span class="token punctuation">(</span></span>
<span class="line">        <span class="token function">strlen</span><span class="token punctuation">(</span><span class="token variable">$state</span><span class="token punctuation">)</span> <span class="token operator">></span> <span class="token number">0</span> <span class="token operator">&amp;&amp;</span> <span class="token variable">$state</span> <span class="token operator">===</span> <span class="token variable">$request</span><span class="token operator">-></span><span class="token property">state</span><span class="token punctuation">,</span></span>
<span class="line">        <span class="token class-name static-context">InvalidArgumentException</span><span class="token operator">::</span><span class="token keyword">class</span></span>
<span class="line">    <span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">    <span class="token variable">$response</span> <span class="token operator">=</span> <span class="token class-name static-context">Http</span><span class="token operator">::</span><span class="token function">asForm</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">post</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'http://passport-app.test/oauth/token'</span><span class="token punctuation">,</span> <span class="token punctuation">[</span></span>
<span class="line">        <span class="token string single-quoted-string">'grant_type'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'authorization_code'</span><span class="token punctuation">,</span></span>
<span class="line">        <span class="token string single-quoted-string">'client_id'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'client-id'</span><span class="token punctuation">,</span></span>
<span class="line">        <span class="token string single-quoted-string">'redirect_uri'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'http://third-party-app.com/callback'</span><span class="token punctuation">,</span></span>
<span class="line">        <span class="token string single-quoted-string">'code_verifier'</span> <span class="token operator">=></span> <span class="token variable">$codeVerifier</span><span class="token punctuation">,</span></span>
<span class="line">        <span class="token string single-quoted-string">'code'</span> <span class="token operator">=></span> <span class="token variable">$request</span><span class="token operator">-></span><span class="token property">code</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">    <span class="token keyword">return</span> <span class="token variable">$response</span><span class="token operator">-></span><span class="token function">json</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h2 id="密码授权令牌" tabindex="-1"><a class="header-anchor" href="#密码授权令牌"><span>密码授权令牌</span></a></h2>
<blockquote>
<p><strong>警告</strong><br>
我们不再推荐使用密码授权令牌。相反，你应该选择<a href="https://oauth2.thephpleague.com/authorization-server/which-grant/" target="_blank" rel="noopener noreferrer">OAuth2服务器当前推荐的授权类型</a>。</p>
</blockquote>
<p>OAuth2密码授权允许你的其他第一方客户端（如移动应用程序）使用电子邮件地址/用户名和密码获取访问令牌。这使你能够向你的第一方客户端安全地发放访问令牌，而无需要求用户经历整个OAuth2授权码重定向流程。</p>
<p>要启用密码授权，可以在应用程序的<code v-pre>App\Providers\AppServiceProvider</code>类的<code v-pre>boot</code>方法中调用<code v-pre>enablePasswordGrant</code>方法：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token doc-comment comment">/**</span>
<span class="line"> * 启动任何应用程序服务。</span>
<span class="line"> */</span></span>
<span class="line"><span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">boot</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token keyword return-type">void</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token class-name static-context">Passport</span><span class="token operator">::</span><span class="token function">enablePasswordGrant</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="创建密码授权客户端" tabindex="-1"><a class="header-anchor" href="#创建密码授权客户端"><span>创建密码授权客户端</span></a></h3>
<p>在你的应用程序可以通过密码授权发放令牌之前，你需要创建一个密码授权客户端。你可以使用<code v-pre>passport:client</code> Artisan命令并加上<code v-pre>--password</code>选项来实现。<strong>如果你已经运行过<code v-pre>passport:install</code>命令，则无需运行此命令：</strong></p>
<div class="language-bash line-numbers-mode" data-highlighter="prismjs" data-ext="sh" data-title="sh"><pre v-pre class="language-bash"><code><span class="line">php artisan passport:client <span class="token parameter variable">--password</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><h3 id="请求令牌-2" tabindex="-1"><a class="header-anchor" href="#请求令牌-2"><span>请求令牌</span></a></h3>
<p>一旦你创建了一个密码授权客户端，你可以通过向<code v-pre>/oauth/token</code>路由发出<code v-pre>POST</code>请求，并提供用户的电子邮件地址和密码来请求访问令牌。请记住，Passport已经注册了这个路由，因此无需手动定义。如果请求成功，你将从服务器的JSON响应中收到<code v-pre>access_token</code>和<code v-pre>refresh_token</code>：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Support<span class="token punctuation">\</span>Facades<span class="token punctuation">\</span>Http</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token variable">$response</span> <span class="token operator">=</span> <span class="token class-name static-context">Http</span><span class="token operator">::</span><span class="token function">asForm</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">post</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'http://passport-app.test/oauth/token'</span><span class="token punctuation">,</span> <span class="token punctuation">[</span></span>
<span class="line">    <span class="token string single-quoted-string">'grant_type'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'password'</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token string single-quoted-string">'client_id'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'client-id'</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token string single-quoted-string">'client_secret'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'client-secret'</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token string single-quoted-string">'username'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'taylor@laravel.com'</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token string single-quoted-string">'password'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'my-password'</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token string single-quoted-string">'scope'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">''</span><span class="token punctuation">,</span></span>
<span class="line"><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">return</span> <span class="token variable">$response</span><span class="token operator">-></span><span class="token function">json</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><blockquote>
<p><strong>注意</strong><br>
请记住，默认情况下访问令牌具有长寿命。但是，如果需要，你可以<a href="#configuration">配置最大访问令牌寿命</a>。</p>
</blockquote>
<h3 id="请求所有范围" tabindex="-1"><a class="header-anchor" href="#请求所有范围"><span>请求所有范围</span></a></h3>
<p>当使用密码授权或客户端凭据授权时，你可能希望为所有受应用程序支持的范围授权令牌。你可以通过请求<code v-pre>*</code>范围来实现这一点。如果请求<code v-pre>*</code>范围，令牌实例上的<code v-pre>can</code>方法将始终返回<code v-pre>true</code>。此范围只能分配给使用<code v-pre>password</code>或<code v-pre>client_credentials</code>授权发放的令牌：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Support<span class="token punctuation">\</span>Facades<span class="token punctuation">\</span>Http</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token variable">$response</span> <span class="token operator">=</span> <span class="token class-name static-context">Http</span><span class="token operator">::</span><span class="token function">asForm</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">post</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'http://passport-app.test/oauth/token'</span><span class="token punctuation">,</span> <span class="token punctuation">[</span></span>
<span class="line">    <span class="token string single-quoted-string">'grant_type'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'password'</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token string single-quoted-string">'client_id'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'client-id'</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token string single-quoted-string">'client_secret'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'client-secret'</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token string single-quoted-string">'username'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'taylor@laravel.com'</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token string single-quoted-string">'password'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'my-password'</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token string single-quoted-string">'scope'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'*'</span><span class="token punctuation">,</span></span>
<span class="line"><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="自定义用户提供程序" tabindex="-1"><a class="header-anchor" href="#自定义用户提供程序"><span>自定义用户提供程序</span></a></h3>
<p>如果你的应用程序使用多个<a href="https://learnku.com/docs/laravel/11.x/authentication#introduction" target="_blank" rel="noopener noreferrer">身份验证用户提供程序</a>，你可以在通过<code v-pre>artisan passport:client --password</code>命令创建客户端时提供<code v-pre>--provider</code>选项，以指定密码授权客户端使用哪个用户提供程序。给定的提供程序名称应与你的应用程序<code v-pre>config/auth.php</code>配置文件中定义的有效提供程序匹配。然后，你可以通过<a href="#via-middleware">使用中间件保护路由</a>来确保只有来自指定提供程序的用户被授权。</p>
<h3 id="自定义用户名字段" tabindex="-1"><a class="header-anchor" href="#自定义用户名字段"><span>自定义用户名字段</span></a></h3>
<p>在使用密码授权进行身份验证时，Passport将使用你的可认证模型的<code v-pre>email</code>属性作为“用户名”。但是，你可以通过在模型上定义一个<code v-pre>findForPassport</code>方法来自定义此行为：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token php language-php"><span class="token delimiter important">&lt;?php</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">namespace</span> <span class="token package">App<span class="token punctuation">\</span>Models</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Foundation<span class="token punctuation">\</span>Auth<span class="token punctuation">\</span>User</span> <span class="token keyword">as</span> Authenticatable<span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Notifications<span class="token punctuation">\</span>Notifiable</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Laravel<span class="token punctuation">\</span>Passport<span class="token punctuation">\</span>HasApiTokens</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">class</span> <span class="token class-name-definition class-name">User</span> <span class="token keyword">extends</span> <span class="token class-name">Authenticatable</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">use</span> <span class="token package">HasApiTokens</span><span class="token punctuation">,</span> Notifiable<span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">    <span class="token doc-comment comment">/**</span>
<span class="line">     * 为给定的用户名查找用户实例。</span>
<span class="line">     */</span></span>
<span class="line">    <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">findForPassport</span><span class="token punctuation">(</span><span class="token keyword type-hint">string</span> <span class="token variable">$username</span><span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token class-name return-type">User</span></span>
<span class="line">    <span class="token punctuation">{</span></span>
<span class="line">        <span class="token keyword">return</span> <span class="token variable">$this</span><span class="token operator">-></span><span class="token function">where</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'username'</span><span class="token punctuation">,</span> <span class="token variable">$username</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">first</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token punctuation">}</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="自定义密码验证" tabindex="-1"><a class="header-anchor" href="#自定义密码验证"><span>自定义密码验证</span></a></h3>
<p>在使用密码授权进行身份验证时，Passport将使用你的模型的<code v-pre>password</code>属性来验证给定的密码。如果你的模型没有<code v-pre>password</code>属性，或者你希望自定义密码验证逻辑，你可以在模型上定义一个<code v-pre>validateForPassportPasswordGrant</code>方法：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token php language-php"><span class="token delimiter important">&lt;?php</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">namespace</span> <span class="token package">App<span class="token punctuation">\</span>Models</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Foundation<span class="token punctuation">\</span>Auth<span class="token punctuation">\</span>User</span> <span class="token keyword">as</span> Authenticatable<span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Notifications<span class="token punctuation">\</span>Notifiable</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Support<span class="token punctuation">\</span>Facades<span class="token punctuation">\</span>Hash</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Laravel<span class="token punctuation">\</span>Passport<span class="token punctuation">\</span>HasApiTokens</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">class</span> <span class="token class-name-definition class-name">User</span> <span class="token keyword">extends</span> <span class="token class-name">Authenticatable</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">use</span> <span class="token package">HasApiTokens</span><span class="token punctuation">,</span> Notifiable<span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">    <span class="token doc-comment comment">/**</span>
<span class="line">     * 验证用户的密码是否符合Passport密码授权要求。</span>
<span class="line">     */</span></span>
<span class="line">    <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">validateForPassportPasswordGrant</span><span class="token punctuation">(</span><span class="token keyword type-hint">string</span> <span class="token variable">$password</span><span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token keyword return-type">bool</span></span>
<span class="line">    <span class="token punctuation">{</span></span>
<span class="line">        <span class="token keyword">return</span> <span class="token class-name static-context">Hash</span><span class="token operator">::</span><span class="token function">check</span><span class="token punctuation">(</span><span class="token variable">$password</span><span class="token punctuation">,</span> <span class="token variable">$this</span><span class="token operator">-></span><span class="token property">password</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token punctuation">}</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h2 id="隐式授权令牌" tabindex="-1"><a class="header-anchor" href="#隐式授权令牌"><span>隐式授权令牌</span></a></h2>
<blockquote>
<p><strong>警告</strong><br>
我们不再推荐使用隐式授权令牌。相反，你应该选择<a href="https://oauth2.thephpleague.com/authorization-server/which-grant/" target="_blank" rel="noopener noreferrer">OAuth2服务器当前推荐的授权类型</a>。</p>
</blockquote>
<p>隐式授权类似于授权码授权；但是，令牌会在不交换授权码的情况下返回给客户端。这种授权通常用于JavaScript或移动应用程序，其中客户端凭据无法安全存储。要启用这种授权，可以在应用程序的<code v-pre>App\Providers\AppServiceProvider</code>类的<code v-pre>boot</code>方法中调用<code v-pre>enableImplicitGrant</code>方法：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token doc-comment comment">/**</span>
<span class="line"> * 启动任何应用程序服务。</span>
<span class="line"> */</span></span>
<span class="line"><span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">boot</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token keyword return-type">void</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token class-name static-context">Passport</span><span class="token operator">::</span><span class="token function">enableImplicitGrant</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>一旦授权被启用，开发人员可以使用他们的客户端ID从你的应用程序请求访问令牌。消费应用程序应该向你的应用程序的<code v-pre>/oauth/authorize</code>路由发出重定向请求，如下所示：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Http<span class="token punctuation">\</span>Request</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token class-name static-context">Route</span><span class="token operator">::</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'/redirect'</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token class-name type-declaration">Request</span> <span class="token variable">$request</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token variable">$request</span><span class="token operator">-></span><span class="token function">session</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">put</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'state'</span><span class="token punctuation">,</span> <span class="token variable">$state</span> <span class="token operator">=</span> <span class="token class-name static-context">Str</span><span class="token operator">::</span><span class="token function">random</span><span class="token punctuation">(</span><span class="token number">40</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">    <span class="token variable">$query</span> <span class="token operator">=</span> <span class="token function">http_build_query</span><span class="token punctuation">(</span><span class="token punctuation">[</span></span>
<span class="line">        <span class="token string single-quoted-string">'client_id'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'client-id'</span><span class="token punctuation">,</span></span>
<span class="line">        <span class="token string single-quoted-string">'redirect_uri'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'http://third-party-app.com/callback'</span><span class="token punctuation">,</span></span>
<span class="line">        <span class="token string single-quoted-string">'response_type'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'token'</span><span class="token punctuation">,</span></span>
<span class="line">        <span class="token string single-quoted-string">'scope'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">''</span><span class="token punctuation">,</span></span>
<span class="line">        <span class="token string single-quoted-string">'state'</span> <span class="token operator">=></span> <span class="token variable">$state</span><span class="token punctuation">,</span></span>
<span class="line">        <span class="token comment">// 'prompt' => '', // "none", "consent", or "login"</span></span>
<span class="line">    <span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">    <span class="token keyword">return</span> <span class="token function">redirect</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'http://passport-app.test/oauth/authorize?'</span> <span class="token operator">.</span> <span class="token variable">$query</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><blockquote>
<p><strong>注意</strong><br>
请记住，<code v-pre>/oauth/authorize</code>路由已经被Passport定义。你无需手动定义此路由。</p>
</blockquote>
<h2 id="客户端凭据授权令牌" tabindex="-1"><a class="header-anchor" href="#客户端凭据授权令牌"><span>客户端凭据授权令牌</span></a></h2>
<p>客户端凭据授权适用于机器对机器的身份验证。例如，你可以在执行API上的维护任务的定时作业中使用此授权。</p>
<p>在你的应用程序可以通过客户端凭据授权发放令牌之前，你需要创建一个客户端凭据授权客户端。你可以使用<code v-pre>passport:client</code> Artisan命令的<code v-pre>--client</code>选项来执行此操作：</p>
<div class="language-bash line-numbers-mode" data-highlighter="prismjs" data-ext="sh" data-title="sh"><pre v-pre class="language-bash"><code><span class="line">php artisan passport:client <span class="token parameter variable">--client</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>接下来，为<code v-pre>CheckClientCredentials</code>中间件注册一个中间件别名以使用此授权类型。你可以在应用程序的<code v-pre>bootstrap/app.php</code>文件中定义中间件别名：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">use</span> <span class="token package">Laravel<span class="token punctuation">\</span>Passport<span class="token punctuation">\</span>Http<span class="token punctuation">\</span>Middleware<span class="token punctuation">\</span>CheckClientCredentials</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token operator">-></span><span class="token function">withMiddleware</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token class-name type-declaration">Middleware</span> <span class="token variable">$middleware</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token variable">$middleware</span><span class="token operator">-></span><span class="token function">alias</span><span class="token punctuation">(</span><span class="token punctuation">[</span></span>
<span class="line">        <span class="token string single-quoted-string">'client'</span> <span class="token operator">=></span> <span class="token class-name static-context">CheckClientCredentials</span><span class="token operator">::</span><span class="token keyword">class</span></span>
<span class="line">    <span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span><span class="token punctuation">)</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>然后，将中间件附加到一个路由上：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token class-name static-context">Route</span><span class="token operator">::</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'/orders'</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token class-name type-declaration">Request</span> <span class="token variable">$request</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token operator">...</span></span>
<span class="line"><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">middleware</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'client'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>如果要限制对路由的访问权限以特定作用域，你可以在将<code v-pre>client</code>中间件附加到路由时提供所需作用域的逗号分隔列表：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token class-name static-context">Route</span><span class="token operator">::</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'/orders'</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token class-name type-declaration">Request</span> <span class="token variable">$request</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token operator">...</span></span>
<span class="line"><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">middleware</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'client:check-status,your-scope'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="检索令牌" tabindex="-1"><a class="header-anchor" href="#检索令牌"><span>检索令牌</span></a></h3>
<p>要使用此授权类型检索令牌，请向<code v-pre>oauth/token</code>端点发出请求：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Support<span class="token punctuation">\</span>Facades<span class="token punctuation">\</span>Http</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token variable">$response</span> <span class="token operator">=</span> <span class="token class-name static-context">Http</span><span class="token operator">::</span><span class="token function">asForm</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">post</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'http://passport-app.test/oauth/token'</span><span class="token punctuation">,</span> <span class="token punctuation">[</span></span>
<span class="line">    <span class="token string single-quoted-string">'grant_type'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'client_credentials'</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token string single-quoted-string">'client_id'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'client-id'</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token string single-quoted-string">'client_secret'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'client-secret'</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token string single-quoted-string">'scope'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'your-scope'</span><span class="token punctuation">,</span></span>
<span class="line"><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">return</span> <span class="token variable">$response</span><span class="token operator">-></span><span class="token function">json</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">[</span><span class="token string single-quoted-string">'access_token'</span><span class="token punctuation">]</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h2 id="个人访问令牌" tabindex="-1"><a class="header-anchor" href="#个人访问令牌"><span>个人访问令牌</span></a></h2>
<p>有时，你的用户可能希望向自己发放访问令牌，而无需经过典型的授权码重定向流程。允许用户通过你的应用程序的UI向自己发放令牌，可以让用户在实验你的API时更加方便，或者作为一种更简单的发放访问令牌的方法。</p>
<blockquote>
<p><strong>注意</strong><br>
如果你的应用程序主要使用Passport发放个人访问令牌，请考虑使用<a href="https://learnku.com/docs/laravel/11.x/sanctum" target="_blank" rel="noopener noreferrer">Laravel Sanctum</a>，这是Laravel的轻量级官方库，用于发放API访问令牌。</p>
</blockquote>
<h3 id="创建个人访问客户端" tabindex="-1"><a class="header-anchor" href="#创建个人访问客户端"><span>创建个人访问客户端</span></a></h3>
<p>在你的应用程序可以发放个人访问令牌之前，你需要创建一个个人访问客户端。你可以通过执行带有<code v-pre>--personal</code>选项的<code v-pre>passport:client</code> Artisan命令来执行此操作。如果你已经运行过<code v-pre>passport:install</code>命令，则无需运行此命令：</p>
<div class="language-bash line-numbers-mode" data-highlighter="prismjs" data-ext="sh" data-title="sh"><pre v-pre class="language-bash"><code><span class="line">php artisan passport:client <span class="token parameter variable">--personal</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>创建完个人访问客户端后，将客户端的ID和明文密钥值放入你的应用程序的<code v-pre>.env</code>文件中：</p>
<div class="language-ini line-numbers-mode" data-highlighter="prismjs" data-ext="ini" data-title="ini"><pre v-pre class="language-ini"><code><span class="line"><span class="token key attr-name">PASSPORT_PERSONAL_ACCESS_CLIENT_ID</span><span class="token punctuation">=</span><span class="token value attr-value">"<span class="token inner-value">client-id-value</span>"</span></span>
<span class="line"><span class="token key attr-name">PASSPORT_PERSONAL_ACCESS_CLIENT_SECRET</span><span class="token punctuation">=</span><span class="token value attr-value">"<span class="token inner-value">unhashed-client-secret-value</span>"</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="管理个人访问令牌" tabindex="-1"><a class="header-anchor" href="#管理个人访问令牌"><span>管理个人访问令牌</span></a></h3>
<p>创建完个人访问客户端后，你可以使用<code v-pre>App\Models\User</code>模型实例上的<code v-pre>createToken</code>方法为特定用户发放令牌。<code v-pre>createToken</code>方法接受令牌名称作为第一个参数，以及可选的<a href="#token-scopes">作用域</a>数组作为第二个参数：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">use</span> <span class="token package">App<span class="token punctuation">\</span>Models<span class="token punctuation">\</span>User</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token variable">$user</span> <span class="token operator">=</span> <span class="token class-name static-context">User</span><span class="token operator">::</span><span class="token function">find</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token comment">// 创建不带作用域的令牌...</span></span>
<span class="line"><span class="token variable">$token</span> <span class="token operator">=</span> <span class="token variable">$user</span><span class="token operator">-></span><span class="token function">createToken</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'Token Name'</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token property">accessToken</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token comment">// 创建带作用域的令牌...</span></span>
<span class="line"><span class="token variable">$token</span> <span class="token operator">=</span> <span class="token variable">$user</span><span class="token operator">-></span><span class="token function">createToken</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'My Token'</span><span class="token punctuation">,</span> <span class="token punctuation">[</span><span class="token string single-quoted-string">'place-orders'</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token property">accessToken</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h4 id="json-api-2" tabindex="-1"><a class="header-anchor" href="#json-api-2"><span>JSON API</span></a></h4>
<p>Passport还包括一个用于管理个人访问令牌的JSON API。你可以将其与自己的前端配对，为用户提供一个管理个人访问令牌的仪表板。接下来，我们将查看管理个人访问令牌的所有API端点。为了方便起见，我们将使用<a href="https://github.com/mzabriskie/axios" target="_blank" rel="noopener noreferrer">Axios</a>来演示如何向这些端点发出HTTP请求。</p>
<p>JSON API由<code v-pre>web</code>和<code v-pre>auth</code>中间件保护；因此，它只能从你自己的应用程序中调用。无法从外部来源调用。</p>
<h4 id="get-oauth-scopes" tabindex="-1"><a class="header-anchor" href="#get-oauth-scopes"><span><code v-pre>GET /oauth/scopes</code></span></a></h4>
<p>该路由返回为你的应用程序定义的所有<a href="#token-scopes">作用域</a>。你可以使用这个路由列出用户可以分配给个人访问令牌的作用域：</p>
<div class="language-javascript line-numbers-mode" data-highlighter="prismjs" data-ext="js" data-title="js"><pre v-pre class="language-javascript"><code><span class="line">axios<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string">'/oauth/scopes'</span><span class="token punctuation">)</span></span>
<span class="line">    <span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token parameter">response</span> <span class="token operator">=></span> <span class="token punctuation">{</span></span>
<span class="line">        console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>response<span class="token punctuation">.</span>data<span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h4 id="get-oauth-personal-access-tokens" tabindex="-1"><a class="header-anchor" href="#get-oauth-personal-access-tokens"><span><code v-pre>GET /oauth/personal-access-tokens</code></span></a></h4>
<p>该路由返回认证用户创建的所有个人访问令牌。主要用于列出用户的所有令牌，以便他们可以编辑或撤销这些令牌：</p>
<div class="language-javascript line-numbers-mode" data-highlighter="prismjs" data-ext="js" data-title="js"><pre v-pre class="language-javascript"><code><span class="line">axios<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string">'/oauth/personal-access-tokens'</span><span class="token punctuation">)</span></span>
<span class="line">    <span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token parameter">response</span> <span class="token operator">=></span> <span class="token punctuation">{</span></span>
<span class="line">        console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>response<span class="token punctuation">.</span>data<span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h4 id="post-oauth-personal-access-tokens" tabindex="-1"><a class="header-anchor" href="#post-oauth-personal-access-tokens"><span><code v-pre>POST /oauth/personal-access-tokens</code></span></a></h4>
<p>该路由创建新的个人访问令牌。它需要两个数据：令牌的 <code v-pre>name</code> 和应分配给令牌的 <code v-pre>scopes</code>：</p>
<div class="language-javascript line-numbers-mode" data-highlighter="prismjs" data-ext="js" data-title="js"><pre v-pre class="language-javascript"><code><span class="line"><span class="token keyword">const</span> data <span class="token operator">=</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token literal-property property">name</span><span class="token operator">:</span> <span class="token string">'令牌名称'</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token literal-property property">scopes</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token punctuation">]</span></span>
<span class="line"><span class="token punctuation">}</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">axios<span class="token punctuation">.</span><span class="token function">post</span><span class="token punctuation">(</span><span class="token string">'/oauth/personal-access-tokens'</span><span class="token punctuation">,</span> data<span class="token punctuation">)</span></span>
<span class="line">    <span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token parameter">response</span> <span class="token operator">=></span> <span class="token punctuation">{</span></span>
<span class="line">        console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>response<span class="token punctuation">.</span>data<span class="token punctuation">.</span>accessToken<span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token punctuation">}</span><span class="token punctuation">)</span></span>
<span class="line">    <span class="token punctuation">.</span><span class="token function">catch</span> <span class="token punctuation">(</span><span class="token parameter">response</span> <span class="token operator">=></span> <span class="token punctuation">{</span></span>
<span class="line">        <span class="token comment">// 在响应中列出错误...</span></span>
<span class="line">    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h4 id="delete-oauth-personal-access-tokens-token-id" tabindex="-1"><a class="header-anchor" href="#delete-oauth-personal-access-tokens-token-id"><span><code v-pre>DELETE /oauth/personal-access-tokens/{token-id}</code></span></a></h4>
<p>该路由可用于撤销个人访问令牌：</p>
<div class="language-javascript line-numbers-mode" data-highlighter="prismjs" data-ext="js" data-title="js"><pre v-pre class="language-javascript"><code><span class="line">axios<span class="token punctuation">.</span><span class="token function">delete</span><span class="token punctuation">(</span><span class="token string">'/oauth/personal-access-tokens/'</span> <span class="token operator">+</span> tokenId<span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><h2 id="保护路由" tabindex="-1"><a class="header-anchor" href="#保护路由"><span>保护路由</span></a></h2>
<h3 id="通过中间件" tabindex="-1"><a class="header-anchor" href="#通过中间件"><span>通过中间件</span></a></h3>
<p>Passport 包含一个<a href="https://learnku.com/docs/laravel/11.x/authentication#adding-custom-guards" target="_blank" rel="noopener noreferrer">身份验证守卫</a>，用于验证传入请求的访问令牌。一旦你配置了 <code v-pre>api</code> 守卫使用 <code v-pre>passport</code> 驱动程序，你只需要在任何需要有效访问令牌的路由上指定 <code v-pre>auth:api</code> 中间件：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token class-name static-context">Route</span><span class="token operator">::</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'/user'</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token comment">// ...</span></span>
<span class="line"><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">middleware</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'auth:api'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><blockquote>
<p><strong>警告</strong><br>
如果你正在使用<a href="#client-credentials-grant-tokens">客户端凭证授权</a>，你应该使用<a href="#client-credentials-grant-tokens">客户端中间件</a>来保护你的路由，而不是 <code v-pre>auth:api</code> 中间件。</p>
</blockquote>
<h4 id="多个身份验证守卫" tabindex="-1"><a class="header-anchor" href="#多个身份验证守卫"><span>多个身份验证守卫</span></a></h4>
<p>如果你的应用程序对不同类型的用户进行身份验证，可能使用完全不同的 Eloquent 模型，你可能需要为应用程序中的每种用户提供程序类型定义一个守卫配置。这样可以保护特定用户提供程序的请求。例如，考虑以下在 <code v-pre>config/auth.php</code> 配置文件中的守卫配置：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token string single-quoted-string">'api'</span> <span class="token operator">=></span> <span class="token punctuation">[</span></span>
<span class="line">    <span class="token string single-quoted-string">'driver'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'passport'</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token string single-quoted-string">'provider'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'users'</span><span class="token punctuation">,</span></span>
<span class="line"><span class="token punctuation">]</span><span class="token punctuation">,</span></span>
<span class="line"></span>
<span class="line"><span class="token string single-quoted-string">'api-customers'</span> <span class="token operator">=></span> <span class="token punctuation">[</span></span>
<span class="line">    <span class="token string single-quoted-string">'driver'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'passport'</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token string single-quoted-string">'provider'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'customers'</span><span class="token punctuation">,</span></span>
<span class="line"><span class="token punctuation">]</span><span class="token punctuation">,</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>以下路由将使用 <code v-pre>api-customers</code> 守卫，该守卫使用 <code v-pre>customers</code> 用户提供程序来验证传入请求：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token class-name static-context">Route</span><span class="token operator">::</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'/customer'</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token comment">// ...</span></span>
<span class="line"><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">middleware</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'auth:api-customers'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><blockquote>
<p><strong>注意</strong><br>
关于如何在 Passport 中使用多个用户提供程序的更多信息，请参考<a href="#customizing-the-user-provider">密码授权文档</a>。</p>
</blockquote>
<h3 id="传递访问令牌" tabindex="-1"><a class="header-anchor" href="#传递访问令牌"><span>传递访问令牌</span></a></h3>
<p>当调用由 Passport 保护的路由时，你的应用程序的 API 消费者应该将他们的访问令牌作为请求的 <code v-pre>Authorization</code> 头部中的 <code v-pre>Bearer</code> 令牌指定。例如，当使用 Guzzle HTTP 库时：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Support<span class="token punctuation">\</span>Facades<span class="token punctuation">\</span>Http</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token variable">$response</span> <span class="token operator">=</span> <span class="token class-name static-context">Http</span><span class="token operator">::</span><span class="token function">withHeaders</span><span class="token punctuation">(</span><span class="token punctuation">[</span></span>
<span class="line">    <span class="token string single-quoted-string">'Accept'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'application/json'</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token string single-quoted-string">'Authorization'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'Bearer '</span><span class="token operator">.</span><span class="token variable">$accessToken</span><span class="token punctuation">,</span></span>
<span class="line"><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'https://passport-app.test/api/user'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">return</span> <span class="token variable">$response</span><span class="token operator">-></span><span class="token function">json</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h2 id="令牌作用域" tabindex="-1"><a class="header-anchor" href="#令牌作用域"><span>令牌作用域</span></a></h2>
<p>作用域允许你的 API 客户端在请求授权以访问账户时请求特定权限集。例如，如果你正在构建一个电子商务应用程序，不是所有的 API 消费者都需要具有下订单的能力。相反，你可以允许消费者仅请求授权以访问订单发货状态。换句话说，作用域允许你的应用程序用户限制第三方应用程序代表他们执行的操作。</p>
<h3 id="定义作用域" tabindex="-1"><a class="header-anchor" href="#定义作用域"><span>定义作用域</span></a></h3>
<p>你可以使用 <code v-pre>Passport::tokensCan</code> 方法在你的应用程序的 <code v-pre>App\Providers\AppServiceProvider</code> 类的 <code v-pre>boot</code> 方法中定义 API 的作用域。<code v-pre>tokensCan</code> 方法接受一个作用域名称和作用域描述的数组。作用域描述可以是任何你希望的内容，并将显示在授权批准屏幕上供用户查看：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token doc-comment comment">/**</span>
<span class="line"> * 引导任何应用服务。</span>
<span class="line"> */</span></span>
<span class="line"><span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">boot</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token keyword return-type">void</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token class-name static-context">Passport</span><span class="token operator">::</span><span class="token function">tokensCan</span><span class="token punctuation">(</span><span class="token punctuation">[</span></span>
<span class="line">        <span class="token string single-quoted-string">'place-orders'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'下订单'</span><span class="token punctuation">,</span></span>
<span class="line">        <span class="token string single-quoted-string">'check-status'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'检查订单状态'</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="默认作用域" tabindex="-1"><a class="header-anchor" href="#默认作用域"><span>默认作用域</span></a></h3>
<p>如果客户端没有请求任何特定作用域，你可以配置你的 Passport 服务器使用 <code v-pre>setDefaultScope</code> 方法将默认作用域附加到令牌上。通常，你应该从你的应用程序的 <code v-pre>App\Providers\AppServiceProvider</code> 类的 <code v-pre>boot</code> 方法中调用这个方法：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">use</span> <span class="token package">Laravel<span class="token punctuation">\</span>Passport<span class="token punctuation">\</span>Passport</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token class-name static-context">Passport</span><span class="token operator">::</span><span class="token function">tokensCan</span><span class="token punctuation">(</span><span class="token punctuation">[</span></span>
<span class="line">    <span class="token string single-quoted-string">'place-orders'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'下订单'</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token string single-quoted-string">'check-status'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'检查订单状态'</span><span class="token punctuation">,</span></span>
<span class="line"><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token class-name static-context">Passport</span><span class="token operator">::</span><span class="token function">setDefaultScope</span><span class="token punctuation">(</span><span class="token punctuation">[</span></span>
<span class="line">    <span class="token string single-quoted-string">'check-status'</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token string single-quoted-string">'place-orders'</span><span class="token punctuation">,</span></span>
<span class="line"><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><blockquote>
<p><strong>注意</strong><br>
Passport 的默认作用域不适用于用户生成的个人访问令牌。</p>
</blockquote>
<h3 id="将作用域分配给令牌" tabindex="-1"><a class="header-anchor" href="#将作用域分配给令牌"><span>将作用域分配给令牌</span></a></h3>
<h4 id="请求授权码时" tabindex="-1"><a class="header-anchor" href="#请求授权码时"><span>请求授权码时</span></a></h4>
<p>在使用授权码授权请求访问令牌时，消费者应将他们所需的作用域指定为 <code v-pre>scope</code> 查询字符串参数。<code v-pre>scope</code> 参数应该是一个以空格分隔的作用域列表：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token class-name static-context">Route</span><span class="token operator">::</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'/redirect'</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token variable">$query</span> <span class="token operator">=</span> <span class="token function">http_build_query</span><span class="token punctuation">(</span><span class="token punctuation">[</span></span>
<span class="line">        <span class="token string single-quoted-string">'client_id'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'client-id'</span><span class="token punctuation">,</span></span>
<span class="line">        <span class="token string single-quoted-string">'redirect_uri'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'http://example.com/callback'</span><span class="token punctuation">,</span></span>
<span class="line">        <span class="token string single-quoted-string">'response_type'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'code'</span><span class="token punctuation">,</span></span>
<span class="line">        <span class="token string single-quoted-string">'scope'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'place-orders check-status'</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">    <span class="token keyword">return</span> <span class="token function">redirect</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'http://passport-app.test/oauth/authorize?'</span><span class="token operator">.</span><span class="token variable">$query</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h4 id="发放个人访问令牌时" tabindex="-1"><a class="header-anchor" href="#发放个人访问令牌时"><span>发放个人访问令牌时</span></a></h4>
<p>如果你正在使用 <code v-pre>App\Models\User</code> 模型的 <code v-pre>createToken</code> 方法发放个人访问令牌，你可以将所需作用域的数组作为方法的第二个参数传递：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token variable">$token</span> <span class="token operator">=</span> <span class="token variable">$user</span><span class="token operator">-></span><span class="token function">createToken</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'My Token'</span><span class="token punctuation">,</span> <span class="token punctuation">[</span><span class="token string single-quoted-string">'place-orders'</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token property">accessToken</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><h3 id="检查作用域" tabindex="-1"><a class="header-anchor" href="#检查作用域"><span>检查作用域</span></a></h3>
<p>Passport 包含两个中间件，可用于验证传入请求是否使用被授予特定作用域的令牌进行身份验证。要开始，请在你的应用程序的 <code v-pre>bootstrap/app.php</code> 文件中定义以下中间件别名：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">use</span> <span class="token package">Laravel<span class="token punctuation">\</span>Passport<span class="token punctuation">\</span>Http<span class="token punctuation">\</span>Middleware<span class="token punctuation">\</span>CheckForAnyScope</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Laravel<span class="token punctuation">\</span>Passport<span class="token punctuation">\</span>Http<span class="token punctuation">\</span>Middleware<span class="token punctuation">\</span>CheckScopes</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token operator">-></span><span class="token function">withMiddleware</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token class-name type-declaration">Middleware</span> <span class="token variable">$middleware</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token variable">$middleware</span><span class="token operator">-></span><span class="token function">alias</span><span class="token punctuation">(</span><span class="token punctuation">[</span></span>
<span class="line">        <span class="token string single-quoted-string">'scopes'</span> <span class="token operator">=></span> <span class="token class-name static-context">CheckScopes</span><span class="token operator">::</span><span class="token keyword">class</span><span class="token punctuation">,</span></span>
<span class="line">        <span class="token string single-quoted-string">'scope'</span> <span class="token operator">=></span> <span class="token class-name static-context">CheckForAnyScope</span><span class="token operator">::</span><span class="token keyword">class</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span><span class="token punctuation">)</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h4 id="检查所有作用域" tabindex="-1"><a class="header-anchor" href="#检查所有作用域"><span>检查所有作用域</span></a></h4>
<p><code v-pre>scopes</code> 中间件可以分配给一个路由，以验证传入请求的访问令牌是否具有所有列出的作用域：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token class-name static-context">Route</span><span class="token operator">::</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'/orders'</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token comment">// 访问令牌具有 "check-status" 和 "place-orders" 作用域...</span></span>
<span class="line"><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">middleware</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token string single-quoted-string">'auth:api'</span><span class="token punctuation">,</span> <span class="token string single-quoted-string">'scopes:check-status,place-orders'</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h4 id="检查任意作用域" tabindex="-1"><a class="header-anchor" href="#检查任意作用域"><span>检查任意作用域</span></a></h4>
<p><code v-pre>scope</code> 中间件可以分配给一个路由，以验证传入请求的访问令牌是否具有<em>至少一个</em>列出的作用域：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token class-name static-context">Route</span><span class="token operator">::</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'/orders'</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token comment">// 访问令牌具有 "check-status" 或 "place-orders" 作用域之一...</span></span>
<span class="line"><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">middleware</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token string single-quoted-string">'auth:api'</span><span class="token punctuation">,</span> <span class="token string single-quoted-string">'scope:check-status,place-orders'</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h4 id="在令牌实例上检查作用域" tabindex="-1"><a class="header-anchor" href="#在令牌实例上检查作用域"><span>在令牌实例上检查作用域</span></a></h4>
<p>一旦访问令牌认证请求进入你的应用程序，你仍然可以使用经过身份验证的 <code v-pre>App\Models\User</code> 实例上的 <code v-pre>tokenCan</code> 方法来检查令牌是否具有给定作用域：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Http<span class="token punctuation">\</span>Request</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token class-name static-context">Route</span><span class="token operator">::</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'/orders'</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token class-name type-declaration">Request</span> <span class="token variable">$request</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token variable">$request</span><span class="token operator">-></span><span class="token function">user</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">tokenCan</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'place-orders'</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">        <span class="token comment">// ...</span></span>
<span class="line">    <span class="token punctuation">}</span></span>
<span class="line"><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h4 id="其他作用域方法" tabindex="-1"><a class="header-anchor" href="#其他作用域方法"><span>其他作用域方法</span></a></h4>
<p><code v-pre>scopeIds</code> 方法将返回所有已定义的 ID / 名称的数组：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">use</span> <span class="token package">Laravel<span class="token punctuation">\</span>Passport<span class="token punctuation">\</span>Passport</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token class-name static-context">Passport</span><span class="token operator">::</span><span class="token function">scopeIds</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><code v-pre>scopes</code> 方法将返回所有已定义作用域的数组，作用域是 <code v-pre>Laravel\Passport\Scope</code> 的实例：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token class-name static-context">Passport</span><span class="token operator">::</span><span class="token function">scopes</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p><code v-pre>scopesFor</code> 方法将返回与给定 ID / 名称匹配的 <code v-pre>Laravel\Passport\Scope</code> 实例数组：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token class-name static-context">Passport</span><span class="token operator">::</span><span class="token function">scopesFor</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token string single-quoted-string">'place-orders'</span><span class="token punctuation">,</span> <span class="token string single-quoted-string">'check-status'</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>你可以使用 <code v-pre>hasScope</code> 方法来确定给定作用域是否已定义：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token class-name static-context">Passport</span><span class="token operator">::</span><span class="token function">hasScope</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'place-orders'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><h2 id="使用-javascript-消费你的-api" tabindex="-1"><a class="header-anchor" href="#使用-javascript-消费你的-api"><span>使用 JavaScript 消费你的 API</span></a></h2>
<p>在构建 API 时，能够从你的 JavaScript 应用程序中消费自己的 API 是非常有用的。这种 API 开发方法允许你的应用程序消费与你与世界共享的相同 API。同一个 API 可以被你的 Web 应用程序、移动应用程序、第三方应用程序以及你可能在各种包管理器上发布的任何 SDK 消费。</p>
<p>通常情况下，如果你想从你的 JavaScript 应用程序中消费你的 API，你需要手动向应用程序发送一个访问令牌，并在每个请求中传递它到你的应用程序。然而，Passport 包含一个可以为你处理这个过程的中间件。你只需要将 <code v-pre>CreateFreshApiToken</code> 中间件附加到应用程序的 <code v-pre>bootstrap/app.php</code> 文件中的 <code v-pre>web</code> 中间件组：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">use</span> <span class="token package">Laravel<span class="token punctuation">\</span>Passport<span class="token punctuation">\</span>Http<span class="token punctuation">\</span>Middleware<span class="token punctuation">\</span>CreateFreshApiToken</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token operator">-></span><span class="token function">withMiddleware</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token class-name type-declaration">Middleware</span> <span class="token variable">$middleware</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token variable">$middleware</span><span class="token operator">-></span><span class="token function">web</span><span class="token punctuation">(</span><span class="token argument-name">append</span><span class="token punctuation">:</span> <span class="token punctuation">[</span></span>
<span class="line">        <span class="token class-name static-context">CreateFreshApiToken</span><span class="token operator">::</span><span class="token keyword">class</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span><span class="token punctuation">)</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><blockquote>
<p><strong>警告</strong><br>
你应该确保 <code v-pre>CreateFreshApiToken</code> 中间件是中间件堆栈中列出的最后一个中间件。</p>
</blockquote>
<p>这个中间件将在你的响应中附加一个 <code v-pre>laravel_token</code> cookie。该 cookie 包含一个加密的 JWT，Passport 将使用它来验证来自你的 JavaScript 应用程序的 API 请求。JWT 的生命周期等于你的 <code v-pre>session.lifetime</code> 配置值。现在，由于浏览器将自动发送该 cookie 到所有后续请求，你可以在不显式传递访问令牌的情况下向你的应用程序 API 发送请求：</p>
<div class="language-javascript line-numbers-mode" data-highlighter="prismjs" data-ext="js" data-title="js"><pre v-pre class="language-javascript"><code><span class="line">axios<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string">'/api/user'</span><span class="token punctuation">)</span></span>
<span class="line">    <span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token parameter">response</span> <span class="token operator">=></span> <span class="token punctuation">{</span></span>
<span class="line">        console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>response<span class="token punctuation">.</span>data<span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h4 id="自定义-cookie-名称" tabindex="-1"><a class="header-anchor" href="#自定义-cookie-名称"><span>自定义 Cookie 名称</span></a></h4>
<p>如果需要，你可以使用<code v-pre>Passport::cookie</code>方法来自定义<code v-pre>laravel_token</code>cookie的名称。通常，这个方法应该从你的应用程序的<code v-pre>App\Providers\AppServiceProvider</code>类的<code v-pre>boot</code>方法中调用：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token doc-comment comment">/**</span>
<span class="line"> * Bootstrap any application services.</span>
<span class="line"> */</span></span>
<span class="line"><span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">boot</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token keyword return-type">void</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token class-name static-context">Passport</span><span class="token operator">::</span><span class="token function">cookie</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'custom_name'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h4 id="csrf-保护" tabindex="-1"><a class="header-anchor" href="#csrf-保护"><span>CSRF 保护</span></a></h4>
<p>在使用这种身份验证方法时，你需要确保请求中包含有效的CSRF令牌头。默认的Laravel JavaScript支架包含一个Axios实例，它将自动使用加密的<code v-pre>XSRF-TOKEN</code> cookie值在同源请求中发送<code v-pre>X-XSRF-TOKEN</code>头。</p>
<blockquote>
<p><strong>注意</strong><br>
如果选择发送<code v-pre>X-CSRF-TOKEN</code>头而不是<code v-pre>X-XSRF-TOKEN</code>，你需要使用<code v-pre>csrf_token()</code>提供的未加密令牌。</p>
</blockquote>
<h2 id="事件" tabindex="-1"><a class="header-anchor" href="#事件"><span>事件</span></a></h2>
<p>在发放访问令牌和刷新令牌时，Passport会触发事件。你可以<a href="https://learnku.com/docs/laravel/11.x/events" target="_blank" rel="noopener noreferrer">监听这些事件</a>来清理或撤销数据库中的其他访问令牌：</p>
<table>
<thead>
<tr>
<th>事件名称</th>
</tr>
</thead>
<tbody>
<tr>
<td><code v-pre>Laravel\Passport\Events\AccessTokenCreated</code></td>
</tr>
<tr>
<td><code v-pre>Laravel\Passport\Events\RefreshTokenCreated</code></td>
</tr>
</tbody>
</table>
<h2 id="测试" tabindex="-1"><a class="header-anchor" href="#测试"><span>测试</span></a></h2>
<p>Passport的<code v-pre>actingAs</code>方法可用于指定当前认证的用户及其作用域。<code v-pre>actingAs</code>方法的第一个参数是用户实例，第二个参数是应授予用户令牌的作用域数组：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">use</span> <span class="token package">App<span class="token punctuation">\</span>Models<span class="token punctuation">\</span>User</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Laravel<span class="token punctuation">\</span>Passport<span class="token punctuation">\</span>Passport</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token function">test</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'servers can be created'</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token class-name static-context">Passport</span><span class="token operator">::</span><span class="token function">actingAs</span><span class="token punctuation">(</span></span>
<span class="line">        <span class="token class-name static-context">User</span><span class="token operator">::</span><span class="token function">factory</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">create</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span></span>
<span class="line">        <span class="token punctuation">[</span><span class="token string single-quoted-string">'create-servers'</span><span class="token punctuation">]</span></span>
<span class="line">    <span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">    <span class="token variable">$response</span> <span class="token operator">=</span> <span class="token variable">$this</span><span class="token operator">-></span><span class="token function">post</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'/api/create-server'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">    <span class="token variable">$response</span><span class="token operator">-></span><span class="token function">assertStatus</span><span class="token punctuation">(</span><span class="token number">201</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">use</span> <span class="token package">App<span class="token punctuation">\</span>Models<span class="token punctuation">\</span>User</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Laravel<span class="token punctuation">\</span>Passport<span class="token punctuation">\</span>Passport</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">test_servers_can_be_created</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token keyword return-type">void</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token class-name static-context">Passport</span><span class="token operator">::</span><span class="token function">actingAs</span><span class="token punctuation">(</span></span>
<span class="line">        <span class="token class-name static-context">User</span><span class="token operator">::</span><span class="token function">factory</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">create</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span></span>
<span class="line">        <span class="token punctuation">[</span><span class="token string single-quoted-string">'create-servers'</span><span class="token punctuation">]</span></span>
<span class="line">    <span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">    <span class="token variable">$response</span> <span class="token operator">=</span> <span class="token variable">$this</span><span class="token operator">-></span><span class="token function">post</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'/api/create-server'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">    <span class="token variable">$response</span><span class="token operator">-></span><span class="token function">assertStatus</span><span class="token punctuation">(</span><span class="token number">201</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>Passport的<code v-pre>actingAsClient</code>方法可用于指定当前认证的客户端及其作用域。<code v-pre>actingAsClient</code>方法的第一个参数是客户端实例，第二个参数是应授予客户端令牌的作用域数组：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">use</span> <span class="token package">Laravel<span class="token punctuation">\</span>Passport<span class="token punctuation">\</span>Client</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Laravel<span class="token punctuation">\</span>Passport<span class="token punctuation">\</span>Passport</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token function">test</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'orders can be retrieved'</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token class-name static-context">Passport</span><span class="token operator">::</span><span class="token function">actingAsClient</span><span class="token punctuation">(</span></span>
<span class="line">        <span class="token class-name static-context">Client</span><span class="token operator">::</span><span class="token function">factory</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">create</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span></span>
<span class="line">        <span class="token punctuation">[</span><span class="token string single-quoted-string">'check-status'</span><span class="token punctuation">]</span></span>
<span class="line">    <span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">    <span class="token variable">$response</span> <span class="token operator">=</span> <span class="token variable">$this</span><span class="token operator">-></span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'/api/orders'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">    <span class="token variable">$response</span><span class="token operator">-></span><span class="token function">assertStatus</span><span class="token punctuation">(</span><span class="token number">200</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">use</span> <span class="token package">Laravel<span class="token punctuation">\</span>Passport<span class="token punctuation">\</span>Client</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Laravel<span class="token punctuation">\</span>Passport<span class="token punctuation">\</span>Passport</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">test_orders_can_be_retrieved</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token keyword return-type">void</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token class-name static-context">Passport</span><span class="token operator">::</span><span class="token function">actingAsClient</span><span class="token punctuation">(</span></span>
<span class="line">        <span class="token class-name static-context">Client</span><span class="token operator">::</span><span class="token function">factory</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">create</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span></span>
<span class="line">        <span class="token punctuation">[</span><span class="token string single-quoted-string">'check-status'</span><span class="token punctuation">]</span></span>
<span class="line">    <span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">    <span class="token variable">$response</span> <span class="token operator">=</span> <span class="token variable">$this</span><span class="token operator">-></span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'/api/orders'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">    <span class="token variable">$response</span><span class="token operator">-></span><span class="token function">assertStatus</span><span class="token punctuation">(</span><span class="token number">200</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><blockquote>
<p>本译文仅用于学习和交流目的，转载请务必注明文章译者、出处、和本文链接<br>
我们的翻译工作遵照 <a href="https://learnku.com/docs/guide/cc4.0/6589" target="_blank" rel="noopener noreferrer">CC 协议</a>，如果我们的工作有侵犯到您的权益，请及时联系我们。</p>
</blockquote>
<hr>
<blockquote>
<p>原文地址：<a href="https://learnku.com/docs/laravel/11.x/passportmd/16724" target="_blank" rel="noopener noreferrer">https://learnku.com/docs/laravel/11.x/pa...</a></p>
<p>译文地址：<a href="https://learnku.com/docs/laravel/11.x/passportmd/16724" target="_blank" rel="noopener noreferrer">https://learnku.com/docs/laravel/11.x/pa...</a></p>
</blockquote>
</div></template>


